﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.ComponentModel.Design.Serialization
Imports System.Drawing.Design
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.ComponentModel.Design
    Friend NotInheritable Class WorkflowDesignerEventsCoordinator
        Implements IDisposable
        ' Methods
        Public Sub New(ByVal serviceProvider As IDesignerLoaderHost)
            Me.serviceProvider = serviceProvider
            AddHandler Me.serviceProvider.LoadComplete, New EventHandler(AddressOf Me.OnDesignerReloaded)
            Dim service As IDesignerEventService = [TryCast](Me.serviceProvider.GetService(GetType(IDesignerEventService)),IDesignerEventService)
            If (Not service Is Nothing) Then
                AddHandler service.ActiveDesignerChanged, New ActiveDesignerEventHandler(AddressOf Me.OnActiveDesignerChanged)
            End If
            Dim provider As ITypeProvider = [TryCast](Me.serviceProvider.GetService(GetType(ITypeProvider)),ITypeProvider)
            If (Not provider Is Nothing) Then
                AddHandler provider.TypesChanged, New EventHandler(AddressOf Me.OnTypeSystemTypesChanged)
            End If
            Dim service2 As ISelectionService = [TryCast](Me.serviceProvider.GetService(GetType(ISelectionService)),ISelectionService)
            If (Not service2 Is Nothing) Then
                AddHandler service2.SelectionChanged, New EventHandler(AddressOf Me.OnSelectionChanged)
            End If
            Dim service3 As IComponentChangeService = [TryCast](Me.serviceProvider.GetService(GetType(IComponentChangeService)),IComponentChangeService)
            If (Not service3 Is Nothing) Then
                AddHandler service3.ComponentChanged, New ComponentChangedEventHandler(AddressOf Me.OnComponentChanged)
            End If
            Dim service4 As IPropertyValueUIService = [TryCast](Me.serviceProvider.GetService(GetType(IPropertyValueUIService)),IPropertyValueUIService)
            If (Not service4 Is Nothing) Then
                service4.AddPropertyValueUIHandler(New PropertyValueUIHandler(AddressOf Me.OnPropertyGridAdornments))
            End If
        End Sub

        Private Sub OnActiveDesignerChanged(ByVal sender As Object, ByVal e As ActiveDesignerEventArgs)
            If ((e.NewDesigner Is Me.serviceProvider.GetService(GetType(IDesignerHost))) AndAlso Me.typeSystemTypesChanged) Then
                Me.RefreshTypes
            Else
                Me.RefreshTasks
            End If
        End Sub

        Private Sub OnBindProperty(ByVal context As ITypeDescriptorContext, ByVal descriptor As PropertyDescriptor, ByVal invokedItem As PropertyValueUIItem)
            BindUITypeEditor.EditValue(context)
        End Sub

        Private Sub OnComponentChanged(ByVal sender As Object, ByVal eventArgs As ComponentChangedEventArgs)
            Me.RefreshDesignerActions
        End Sub

        Private Sub OnDesignerReloaded(ByVal sender As Object, ByVal e As EventArgs)
            Dim flag As Boolean = (Not Me.refreshTypesHandler Is Nothing)
            Dim flag2 As Boolean = (Not Me.refreshDesignerActionsHandler Is Nothing)
            Dim flag3 As Boolean = (Not Me.refreshTasksHandler Is Nothing)
            Me.refreshTypesHandler = Nothing
            Me.refreshDesignerActionsHandler = Nothing
            Me.refreshTasksHandler = Nothing
            If ((flag OrElse flag3) OrElse flag2) Then
                Me.RefreshTypes
                Me.RefreshDesignerActions
            End If
        End Sub

        Private Sub OnPropertyGridAdornments(ByVal context As ITypeDescriptorContext, ByVal propDesc As PropertyDescriptor, ByVal valueUIItemList As ArrayList)
            Dim reference As IComponent = Nothing
            Dim service As IReferenceService = [TryCast](Me.serviceProvider.GetService(GetType(IReferenceService)),IReferenceService)
            If (Not service Is Nothing) Then
                reference = service.GetComponent(context.Instance)
            End If
            Dim str As String = String.Empty
            Dim attribute As DefaultPropertyAttribute = [TryCast](propDesc.Attributes.Item(GetType(DefaultPropertyAttribute)),DefaultPropertyAttribute)
            If (((Not attribute Is Nothing) AndAlso (Not attribute.Name Is Nothing)) AndAlso (attribute.Name.Length > 0)) Then
                str = (propDesc.Name & "." & attribute.Name)
            End If
            If (Not reference Is Nothing) Then
                Dim designer As ActivityDesigner = ActivityDesigner.GetDesigner([TryCast](reference,Activity))
                If (Not designer Is Nothing) Then
                    If ((Not designer.IsLocked AndAlso ActivityBindPropertyDescriptor.IsBindableProperty(propDesc)) AndAlso Not propDesc.IsReadOnly) Then
                        valueUIItemList.Add(New PropertyValueUIItem(DR.GetImage("Bind"), New PropertyValueUIItemInvokeHandler(AddressOf Me.OnBindProperty), DR.GetString("BindProperty", New Object(0  - 1) {})))
                    End If
                    Dim name As String = service.GetName(reference)
                    Dim str3 As String = service.GetName(context.Instance)
                    str3 = If((str3.Length > name.Length), (str3.Substring((name.Length + 1), ((str3.Length - name.Length) - 1)) & "." & propDesc.Name), String.Empty)
                    Dim action As DesignerAction
                    For Each action In designer.DesignerActions
                        Dim propertyName As String = action.PropertyName
                        If (((Not propertyName Is Nothing) AndAlso (propertyName.Length <> 0)) AndAlso (((propertyName = propDesc.Name) OrElse (propertyName = str3)) OrElse (propertyName = str))) Then
                            Dim handler As New PropertyValueUIItemHandler(action)
                            valueUIItemList.Add(New PropertyValueUIItem(action.Image, New PropertyValueUIItemInvokeHandler(AddressOf handler.OnFixPropertyError), action.Text))
                            Exit For
                        End If
                    Next
                End If
            End If
        End Sub

        Private Sub OnRefreshDesignerActions(ByVal sender As Object, ByVal e As EventArgs)
            Dim view As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
            If (Not Me.refreshDesignerActionsHandler Is Nothing) Then
                If (Not view Is Nothing) Then
                    RemoveHandler view.Idle, Me.refreshDesignerActionsHandler
                End If
                Me.refreshDesignerActionsHandler = Nothing
            End If
            DesignerHelpers.RefreshDesignerActions(Me.serviceProvider)
            Dim service As IPropertyValueUIService = [TryCast](Me.serviceProvider.GetService(GetType(IPropertyValueUIService)),IPropertyValueUIService)
            If (Not service Is Nothing) Then
                service.NotifyPropertyValueUIItemsChanged
            End If
            Me.RefreshTasks
        End Sub

        Private Sub OnRefreshTasks(ByVal sender As Object, ByVal e As EventArgs)
            Dim view As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
            If (Not Me.refreshTasksHandler Is Nothing) Then
                If (Not view Is Nothing) Then
                    RemoveHandler view.Idle, Me.refreshTasksHandler
                End If
                Me.refreshTasksHandler = Nothing
            End If
            Dim service As ISelectionService = [TryCast](Me.serviceProvider.GetService(GetType(ISelectionService)),ISelectionService)
            Dim service2 As IExtendedUIService = [TryCast](Me.serviceProvider.GetService(GetType(IExtendedUIService)),IExtendedUIService)
            If ((Not service Is Nothing) AndAlso (Not service2 Is Nothing)) Then
                service2.RemoveDesignerActions
                Dim service3 As IDesignerEventService = DirectCast(Me.serviceProvider.GetService(GetType(IDesignerEventService)), IDesignerEventService)
                If ((Not service3 Is Nothing) AndAlso (service3.ActiveDesigner Is Me.serviceProvider.GetService(GetType(IDesignerHost)))) Then
                    Dim obj2 As Object
                    For Each obj2 In service.GetSelectedComponents
                        Dim associatedDesigner As ActivityDesigner = Nothing
                        If TypeOf obj2 Is HitTestInfo Then
                            associatedDesigner = DirectCast(obj2, HitTestInfo).AssociatedDesigner
                        ElseIf TypeOf obj2 Is Activity Then
                            associatedDesigner = ActivityDesigner.GetDesigner([TryCast](obj2,Activity))
                        End If
                        If (Not associatedDesigner Is Nothing) Then
                            service2.AddDesignerActions(New List([Of] DesignerAction)(associatedDesigner.DesignerActions).ToArray)
                        End If
                    Next
                End If
            End If
            If (Not view Is Nothing) Then
                view.Invalidate
            End If
        End Sub

        Private Sub OnRefreshTypes(ByVal sender As Object, ByVal e As EventArgs)
            If (Not Me.refreshTypesHandler Is Nothing) Then
                Dim view As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
                If (Not view Is Nothing) Then
                    RemoveHandler view.Idle, Me.refreshTypesHandler
                End If
                Me.refreshTypesHandler = Nothing
            End If
            Dim host As IDesignerHost = [TryCast](Me.serviceProvider.GetService(GetType(IDesignerHost)),IDesignerHost)
            Dim seedActivity As Activity = If((Not host Is Nothing), [TryCast](host.RootComponent,Activity), Nothing)
            If (Not seedActivity Is Nothing) Then
                Dim typeProvider As ITypeProvider = [TryCast](Me.serviceProvider.GetService(GetType(ITypeProvider)),ITypeProvider)
                If (Not typeProvider Is Nothing) Then
                    Dim class3 As <>c__DisplayClass3
                    Dim CS$<>8__locals4 As <>c__DisplayClass3 = class3
                    Dim walker As New Walker
                    AddHandler walker.FoundProperty, Function (ByVal w As Walker, ByVal args As WalkerEventArgs) 
                        If (((Not args.CurrentValue Is Nothing) AndAlso (Not args.CurrentProperty Is Nothing)) AndAlso ((args.CurrentProperty.PropertyType Is GetType(Type)) AndAlso TypeOf args.CurrentValue Is Type)) Then
                            Dim type As Type = CS$<>8__locals4.typeProvider.GetType(DirectCast(args.CurrentValue, Type).FullName)
                            If (Not type Is Nothing) Then
                                args.CurrentProperty.SetValue(args.CurrentPropertyOwner, type, Nothing)
                                If (Not args.CurrentActivity Is Nothing) Then
                                    TypeDescriptor.Refresh(args.CurrentActivity)
                                End If
                            End If
                        ElseIf (((args.CurrentProperty Is Nothing) AndAlso TypeOf args.CurrentValue Is DependencyObject) AndAlso Not TypeOf args.CurrentValue Is Activity) Then
                            walker.WalkProperties(args.CurrentActivity, args.CurrentValue)
                        End If
                    End Function
                    AddHandler walker.FoundActivity, Function (ByVal w As Walker, ByVal args As WalkerEventArgs) 
                        If (Not args.CurrentActivity Is Nothing) Then
                            TypeDescriptor.Refresh(args.CurrentActivity)
                            Dim designer As ActivityDesigner = ActivityDesigner.GetDesigner(args.CurrentActivity)
                            If (Not designer Is Nothing) Then
                                designer.RefreshDesignerActions
                            End If
                            Dim designer2 As InvokeWorkflowDesigner = [TryCast](designer,InvokeWorkflowDesigner)
                            If (Not designer2 Is Nothing) Then
                                designer2.RefreshTargetWorkflowType
                            End If
                        End If
                    End Function
                    walker.Walk(seedActivity)
                End If
                Dim service As IPropertyValueUIService = [TryCast](Me.serviceProvider.GetService(GetType(IPropertyValueUIService)),IPropertyValueUIService)
                If (Not service Is Nothing) Then
                    service.NotifyPropertyValueUIItemsChanged
                End If
                Me.RefreshTasks
                Me.RefreshDesignerActions
            End If
        End Sub

        Private Sub OnSelectionChanged(ByVal sender As Object, ByVal e As EventArgs)
            Dim service As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
            If (Not service Is Nothing) Then
                service.Invalidate
            End If
            Me.RefreshTasks
        End Sub

        Private Sub OnTypeSystemTypesChanged(ByVal sender As Object, ByVal e As EventArgs)
            Me.typeSystemTypesChanged = True
            Dim service As IDesignerEventService = [TryCast](Me.serviceProvider.GetService(GetType(IDesignerEventService)),IDesignerEventService)
            If ((Not service Is Nothing) AndAlso (service.ActiveDesigner Is Me.serviceProvider.GetService(GetType(IDesignerHost)))) Then
                Me.RefreshTypes
            End If
        End Sub

        Private Sub RefreshDesignerActions()
            If (Me.refreshDesignerActionsHandler Is Nothing) Then
                Dim service As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
                If (Not service Is Nothing) Then
                    Me.refreshDesignerActionsHandler = New EventHandler(AddressOf Me.OnRefreshDesignerActions)
                    AddHandler service.Idle, Me.refreshDesignerActionsHandler
                End If
            End If
        End Sub

        Private Sub RefreshTasks()
            If (Me.refreshTasksHandler Is Nothing) Then
                Dim service As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
                If (Not service Is Nothing) Then
                    Me.refreshTasksHandler = New EventHandler(AddressOf Me.OnRefreshTasks)
                    AddHandler service.Idle, Me.refreshTasksHandler
                End If
            End If
        End Sub

        Private Sub RefreshTypes()
            If ((Me.refreshTypesHandler Is Nothing) AndAlso Me.typeSystemTypesChanged) Then
                Dim service As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
                If (Not service Is Nothing) Then
                    Me.refreshTypesHandler = New EventHandler(AddressOf Me.OnRefreshTypes)
                    AddHandler service.Idle, Me.refreshTypesHandler
                End If
            End If
            Me.typeSystemTypesChanged = False
        End Sub

        Private Sub System.IDisposable.Dispose() Implements IDisposable.Dispose
            Dim view As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
            If (Not view Is Nothing) Then
                If (Not Me.refreshTypesHandler Is Nothing) Then
                    RemoveHandler view.Idle, Me.refreshTypesHandler
                End If
                If (Not Me.refreshDesignerActionsHandler Is Nothing) Then
                    RemoveHandler view.Idle, Me.refreshDesignerActionsHandler
                End If
                If (Not Me.refreshTasksHandler Is Nothing) Then
                    RemoveHandler view.Idle, Me.refreshTasksHandler
                End If
            End If
            Me.refreshTypesHandler = Nothing
            Me.refreshDesignerActionsHandler = Nothing
            Me.refreshTasksHandler = Nothing
            Dim service As IExtendedUIService = [TryCast](Me.serviceProvider.GetService(GetType(IExtendedUIService)),IExtendedUIService)
            If (Not service Is Nothing) Then
                service.RemoveDesignerActions
            End If
            Dim service2 As IPropertyValueUIService = [TryCast](Me.serviceProvider.GetService(GetType(IPropertyValueUIService)),IPropertyValueUIService)
            If (Not service2 Is Nothing) Then
                service2.RemovePropertyValueUIHandler(New PropertyValueUIHandler(AddressOf Me.OnPropertyGridAdornments))
            End If
            Dim service3 As IComponentChangeService = [TryCast](Me.serviceProvider.GetService(GetType(IComponentChangeService)),IComponentChangeService)
            If (Not service3 Is Nothing) Then
                RemoveHandler service3.ComponentChanged, New ComponentChangedEventHandler(AddressOf Me.OnComponentChanged)
            End If
            Dim service4 As ISelectionService = [TryCast](Me.serviceProvider.GetService(GetType(ISelectionService)),ISelectionService)
            If (Not service4 Is Nothing) Then
                RemoveHandler service4.SelectionChanged, New EventHandler(AddressOf Me.OnSelectionChanged)
            End If
            Dim provider As ITypeProvider = [TryCast](Me.serviceProvider.GetService(GetType(ITypeProvider)),ITypeProvider)
            If (Not provider Is Nothing) Then
                RemoveHandler provider.TypesChanged, New EventHandler(AddressOf Me.OnTypeSystemTypesChanged)
            End If
            Dim service5 As IDesignerEventService = [TryCast](Me.serviceProvider.GetService(GetType(IDesignerEventService)),IDesignerEventService)
            If (Not service5 Is Nothing) Then
                RemoveHandler service5.ActiveDesignerChanged, New ActiveDesignerEventHandler(AddressOf Me.OnActiveDesignerChanged)
            End If
            RemoveHandler Me.serviceProvider.LoadComplete, New EventHandler(AddressOf Me.OnDesignerReloaded)
        End Sub


        ' Fields
        Private refreshDesignerActionsHandler As EventHandler
        Private refreshTasksHandler As EventHandler
        Private refreshTypesHandler As EventHandler
        Private serviceProvider As IDesignerLoaderHost
        Private typeSystemTypesChanged As Boolean

        ' Nested Types
        Private Class PropertyValueUIItemHandler
            ' Methods
            Friend Sub New(ByVal action As DesignerAction)
                Me.action = action
            End Sub

            Friend Sub OnFixPropertyError(ByVal context As ITypeDescriptorContext, ByVal descriptor As PropertyDescriptor, ByVal invokedItem As PropertyValueUIItem)
                Me.action.Invoke
            End Sub


            ' Fields
            Private action As DesignerAction
        End Class
    End Class
End Namespace

